package org.changs.nav.ui.nav.mapscene;

import android.location.Location;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.BounceInterpolator;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.animation.Animation;
import com.amap.api.maps.model.animation.ScaleAnimation;
import com.amap.api.services.geocoder.RegeocodeAddress;

import org.changs.aplug.annotation.FragmentScoped;
import org.changs.aplug.interf.OnIntervalClickListener;
import org.changs.aplug.utils.EmptyUtils;
import org.changs.nav.R;
import org.changs.nav.delegate.MapSwitchDelegate;
import org.changs.nav.delegate.amap.GeocodeSearchHelper;
import org.changs.nav.ui.nav.MainActivity;
import org.changs.nav.ui.nav.MainMapFragment;
import org.changs.nav.ui.nav.MarketDetailFragment;
import org.changs.nav.ui.nav.SearchMainFragment;
import org.changs.nav.ui.set.SetMainFragment;

import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

/**
 * Created by yincs on 2017/11/26.
 */

/**
 * 地图的基础功能
 */
@FragmentScoped
public class BasicsMapScene extends AbstractMapScene {

    private final GeocodeSearchHelper mGeocodeSearchHelper;
    private final MapSwitchDelegate mMapSwitchDelegate;


    private LatLng mCenterLatLng;
    private MarkerOptions mCenterMarkerOptions;
    private Marker mCenterMarker;
    private Animation mCenterMarkerAnim;
    private RegeocodeAddress mCenterRegeocodeAddress;
    private boolean isDragMap, isMyLocation;
    private Disposable mDelayShowCenterSubscribe, mDetailAddressSubscribe;
    private final AMap.OnCameraChangeListener mOnCameraChangeListener = new AMap.OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition cameraPosition) {
            if (isDragMap) {
                showDragView();
            }
        }

        @Override
        public void onCameraChangeFinish(CameraPosition cameraPosition) {
            if (isDragMap) {
                mCenterLatLng = cameraPosition.target;
                showDragIdle();
            }
        }
    };
    private final AMap.OnMarkerClickListener mOnMarkerClickListener = new AMap.OnMarkerClickListener() {
        @Override
        public boolean onMarkerClick(Marker marker) {
            if (!marker.equals(mCenterMarker)) {
                return true;
            }
            showCenterDetailAddress();
            return false;
        }
    };
    private final AMap.OnMapTouchListener mOnMapTouchListener = new AMap.OnMapTouchListener() {
        @Override
        public void onTouch(MotionEvent motionEvent) {
            Timber.d("onTouch() called with: motionEvent = [" + motionEvent + "]");
            if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
                isDragMap = true;
                isMyLocation = false;
            }
        }
    };

    @Inject
    public BasicsMapScene(MainMapFragment mapFragment, GeocodeSearchHelper geocodeSearchHelper, MapSwitchDelegate mapSwitchDelegate) {
        super(mapFragment);
        mGeocodeSearchHelper = geocodeSearchHelper;
        mMapSwitchDelegate = mapSwitchDelegate;
    }

    public void init() {
        mCenterMarkerOptions = new MarkerOptions().icon(BitmapDescriptorFactory.fromView(LayoutInflater.from(getContext())
                .inflate(R.layout.amap_marker_center_icon, (ViewGroup) mBinding.getRoot(), false)));

        mBinding.btnGoCar.setOnClickListener(v -> {
            gotoMyLocation();
        });
        mBinding.btnGoDestination.setOnClickListener(new OnIntervalClickListener() {
            @Override
            public void intervalOnClick(View v) {
                mBinding.btnSetting.setVisibility(View.GONE);
                mBinding.btnGoDestination.setVisibility(View.GONE);
                mMapFragment.startFragment(new SearchMainFragment(), MainActivity.TAG_BACK_STACK_DEFAULT);
            }
        });
        mBinding.btnSetting.setOnClickListener(new OnIntervalClickListener() {
            @Override
            public void intervalOnClick(View v) {
                mBinding.btnSetting.setVisibility(View.GONE);
                mBinding.btnGoDestination.setVisibility(View.GONE);
                mMapFragment.startFragment(new SetMainFragment(), MainActivity.TAG_BACK_STACK_DEFAULT);
            }
        });

        mBinding.btnCenter.setVisibility(View.GONE);
        mBinding.vCenter.setVisibility(View.GONE);

        mBinding.btnCenter.setOnClickListener(v -> {
            showCenterDetailAddress();
        });
        mBinding.vCenterAddress.setOnClickListener(v -> {
            showCenterDetailAddress();
        });
        initMapEvent();
    }


    @Override
    public void onCreated(Bundle savedInstanceState) {
        super.onCreated(savedInstanceState);
        init();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {

    }

    @Override
    public void showScene() {
        initMapEvent();
        mBinding.btn2d3d.setVisibility(View.VISIBLE);
        mBinding.btnGoCar.setVisibility(isMyLocation ? View.GONE : View.VISIBLE);
        mBinding.btnSetting.setVisibility(isMyLocation ? View.VISIBLE : View.GONE);
        mBinding.btnGoDestination.setVisibility(isMyLocation ? View.VISIBLE : View.GONE);

        if (mCenterMarker == null) {
            if (mCenterLatLng != null) {
                addCenterMarker();
                getAMap().animateCamera(CameraUpdateFactory.newLatLngZoom(mCenterLatLng, 15));
            } else {
                gotoMyLocation();
            }
        }
    }

    @Override
    public void hideScene() {
        mBinding.btnGoCar.setVisibility(View.GONE);
        if (mCenterMarker != null) {
            mCenterMarker.remove();
            mCenterMarker = null;
        }
    }

    @Override
    public void removeScene() {

    }


    @Override
    protected void initMapEvent() {
        enableMyLocation(true);
        getAMap().setPointToCenter(mBinding.getRoot().getMeasuredWidth() / 2, mBinding.getRoot().getMeasuredHeight() / 2);
        getAMap().setOnCameraChangeListener(mOnCameraChangeListener);
        getAMap().setOnMarkerClickListener(mOnMarkerClickListener);
        getAMap().setOnMapTouchListener(mOnMapTouchListener);
    }


    /**
     * 显示中心点的market
     */
    private void addCenterMarker() {
        mCenterMarker = getAMap().addMarker(mCenterMarkerOptions.position(mCenterLatLng));
        Timber.d("addCenterMarker mCenterMarker = " + mCenterMarker);
    }

    private void startCenterMarkerAnim() {
        if (mCenterMarker == null) return;
        if (mCenterMarkerAnim == null) {
            mCenterMarkerAnim = new ScaleAnimation(0f, 1f, 0f, 1f);
            mCenterMarkerAnim.setDuration(1000L);
            mCenterMarkerAnim.setInterpolator(new BounceInterpolator());
        }
        mCenterMarker.setAnimation(mCenterMarkerAnim);
        mCenterMarker.startAnimation();
    }

    private void showCenterAddress() {
        if (mCenterRegeocodeAddress == null || findMarketDetailFragment() != null) return;
        String address;
        if (EmptyUtils.isEmpty(mCenterRegeocodeAddress.getPois())) {
            address = "地图选点";
        } else {
            address = "在" + mCenterRegeocodeAddress.getPois().get(0).getSnippet() + "附近";
        }
        mBinding.vCenterAddress.setVisibility(View.VISIBLE);
        mBinding.tvCenterAddress.setText(address);
    }

    /**
     * 回车位
     */
    public void gotoMyLocation() {
        isDragMap = false;
        isMyLocation = true;
        final Location location = getAMap().getMyLocation();
        if (location == null) {
            getAMap().setOnMyLocationChangeListener(location1 -> {
                if (location1 != null) {
                    getAMap().setOnMyLocationChangeListener(null);
                    gotoMyLocation();
                }
            });
            return;
        }
        getAMap().animateCamera(CameraUpdateFactory
                .newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 13));

        mBinding.btnSetting.setVisibility(View.VISIBLE);
        mBinding.btnGoDestination.setVisibility(View.VISIBLE);

        mBinding.btnGoCar.setVisibility(View.GONE);
        mBinding.vCenter.setVisibility(View.GONE);
        mBinding.btnCenter.setVisibility(View.GONE);
        mBinding.vCenterAddress.setVisibility(View.GONE);
        if (mDelayShowCenterSubscribe != null) {
            mDelayShowCenterSubscribe.dispose();
            mDelayShowCenterSubscribe = null;
        }
        if (mDetailAddressSubscribe != null) {
            mDetailAddressSubscribe.dispose();
            mDetailAddressSubscribe = null;
        }
        if (mCenterMarker != null) {
            mCenterMarker.remove();
            mCenterMarker = null;
        }
        mCenterLatLng = null;
        mCenterRegeocodeAddress = null;
        MarketDetailFragment marketDetailFragment = findMarketDetailFragment();
        if (marketDetailFragment != null) getContext().getSupportFragmentManager().popBackStack();
    }

    /**
     * 拖动状态
     */
    private void showDragView() {
        if (mBinding.vCenter.getVisibility() != View.VISIBLE) {
            mBinding.btnSetting.setVisibility(View.GONE);
            mBinding.btnGoDestination.setVisibility(View.GONE);
            mBinding.btnCenter.setVisibility(View.GONE);
            mBinding.btnGoCar.setVisibility(View.VISIBLE);
            mBinding.vCenter.setVisibility(View.VISIBLE);

            mBinding.vCenterAddress.setVisibility(View.GONE);
            if (mDelayShowCenterSubscribe != null) {
                mDelayShowCenterSubscribe.dispose();
                mDelayShowCenterSubscribe = null;
            }
            if (mDetailAddressSubscribe != null) {
                mDetailAddressSubscribe.dispose();
                mDetailAddressSubscribe = null;
            }
            if (mCenterMarker != null) {
                mCenterMarker.remove();
                mCenterMarker = null;
            }
            mCenterLatLng = null;
            mCenterRegeocodeAddress = null;
            MarketDetailFragment marketDetailFragment = findMarketDetailFragment();
            if (marketDetailFragment != null)
                getContext().getSupportFragmentManager().popBackStack();
        }
    }

    /**
     * 停止拖动
     */
    private void showDragIdle() {
        mDelayShowCenterSubscribe = Observable.timer(500, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnComplete(() -> mDelayShowCenterSubscribe = null)
                .subscribe(aLong -> {
                    Timber.d("onCameraChangeFinish accept aLong = " + aLong);
                    mBinding.vCenter.setVisibility(View.INVISIBLE);
                    mBinding.btnCenter.setVisibility(View.VISIBLE);
                    isDragMap = false;

                    getDetailAddress();
                });
    }

    /**
     * 加载该marker详细地址
     */
    private void getDetailAddress() {
        mDetailAddressSubscribe = mGeocodeSearchHelper.getFromLocation(mCenterLatLng.latitude, mCenterLatLng.longitude)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnComplete(() -> mDetailAddressSubscribe = null)
                .subscribe(new Consumer<RegeocodeAddress>() {
                    @Override
                    public void accept(RegeocodeAddress regeocodeAddress) throws Exception {
                        mCenterRegeocodeAddress = regeocodeAddress;
                        showCenterAddress();

                        MarketDetailFragment marketDetailFragment = findMarketDetailFragment();
                        if (marketDetailFragment != null) {
                            marketDetailFragment.setRegeocodeAddress(mCenterRegeocodeAddress);
                        }
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        throwable.printStackTrace();
                    }
                });
    }

    /**
     * 显示详细地址
     */
    private void showCenterDetailAddress() {
        mBinding.btnCenter.setVisibility(View.GONE);
        mBinding.vCenterAddress.setVisibility(View.GONE);
        if (mCenterMarker == null) addCenterMarker();
        startCenterMarkerAnim();
        MarketDetailFragment marketDetailFragment = findMarketDetailFragment();
        if (marketDetailFragment == null) {
            marketDetailFragment = MarketDetailFragment.newInstance(mCenterMarker.getPosition());
            mMapFragment.startFragment(marketDetailFragment, MarketDetailFragment.TAG,
                    MainActivity.TAG_BACK_STACK_DEFAULT);
        }
        if (mCenterRegeocodeAddress != null)
            marketDetailFragment.setRegeocodeAddress(mCenterRegeocodeAddress);
    }

    private MarketDetailFragment findMarketDetailFragment() {
        return (MarketDetailFragment) getContext().getSupportFragmentManager().findFragmentByTag(MarketDetailFragment.TAG);
    }


}
